<?php
/**
 * This class contains the factory for selecting the correct
 * database class. This is a DBMS abstraction layer and allows for
 * supporting multiple DBMSs in the future.
 * Handling of the necessary data such as host path, user name etc.
 * is also done in this class.
 * The data is forwarded to the concrete Database object during creation.
 */
class DatabaseFactory {
    private $host = "";             //address of DBMS server
    private $user = "";             //user name for DBMS server
    private $pass = "";             //user password for the DBMS sever
    public  $dbName = "";           //name of database in DBMS
    public  $dbms = "";             //database managment system name

    /**
     * The constructor determines which constructor to
     * call with the given parameters.
     * Hack for multiple constructors: http://ordinarywebguy.wordpress.com/2008/01/31/multiple-constructor-in-php/
     *
     * __construct() calls the default constructor
     * __construct($dbms,$host,$dbName,$user,$pass) can be used to directly provide all login information necessary
     * to connect to a database management system.
     */
   function  __construct() {
        $argv = func_get_args();
        switch( func_num_args() )
        {
            default:
            case 0:
                self::defConstructor();
                break;
            case 5:
                list($dbms,$host,$dbName,$user,$pass) = $argv;
                self::fullDataConstructor($dbms,$host,$dbName,$user,$pass);
                break;
        }
    }
    /**
     * The constructor determines the path to the settings file and then initializes
     * the values for host user etc with the values in the settings file.
     */
    private function  defConstructor() {
        $this->readSettings();
        $this->constructed = true;
    }
    /**
     * This constructor needs all variables to be passed to it.
     * Intended for testing of validity of login during installation.
     * @param <type> $dbms
     * @param <type> $host
     * @param <type> $dbName
     * @param <type> $user
     * @param <type> $pass
     */
    private function  fullDataConstructor($dbms,$host,$dbName,$user,$pass) {
        $this->dbms = strtolower($dbms);
        $this->host = $host;
        $this->dbName = $dbName;
        $this->user = $user;
        $this->pass = $pass;
        $this->constructed = true;
    }
    /**
     * This function returns a database object of the desired
     * DBMS which is already connected.
     * It determines the correct path by resolving the location
     * of the include file for the database class.
     * It must be located in the subfolder with the name of the DBMS
     * and must have the name database.inc.
     */
    public function connect() {
        @include_once('database.inc');
        $db = new Database();
        $db->connect($this->host,$this->dbName,$this->user,$this->pass);
        return($db);
    }
    /**
     * Determines the full path of the settings file with the
     * database host, db, etc.
     * @return the full path
     */
    public function getSettingsLoc() {
        $curLoc = __FILE__;
        $settingsLoc = str_replace("dbFac.inc", "settings.inc", $curLoc);
        return($settingsLoc);
    }
    /**
     * This function uses the current settings to connect to the database.
     * The function assumes that the include path to the selected DBMS has been set.
     * @return <boolean>:   true if successful, false otherwise. 
     */
    public function testSettings() {
        $db = $this->connect();
        if($db->isConnected())
            return(true);
        return(false);
    }
    /**
     * The function writeSettings determines the path to the database settings
     * and writes the current settings to that file, deleting all old content.
     */
    public function writeSettings() {
        $path = $this->getSettingsLoc();
        $fh = fopen($path,"w");
        fwrite($fh,";This file should be read only for scripts \n");
        fwrite($fh,";It should be located in a directory without public access. \n");
        fwrite($fh,"############DBMS Settings###############\n");
        fwrite($fh,"host=" . $this->host . "\n");
        fwrite($fh,"user=" . $this->user . "\n");
        fwrite($fh,"pass=" . $this->pass . "\n");
        fwrite($fh,"dbName=" . $this->dbName . "\n");
        fwrite($fh,"dbms=" . $this->dbms . "\n");
        fclose($fh);

    }
    /**
     * The function readSettings gets all database variables from the settings
     * file and stores the values in the member variables.
     * It ignores comment lines starting with '#' or ';'.
     */
    public function readSettings() {
        $settingsLoc = $this->getSettingsLoc();
        $settingsArray = file($settingsLoc);
        foreach($settingsArray as $line) {
            if(preg_match("/^[#;]/", $line))
                continue;   //A comment line.
            list($varName,$value) = explode("=",$line);
            $value = trim($value);
            $value = str_replace(";", "", $value);
            switch(strToLower($varName))
            {
                case 'host';
                    $this->host = $value;
                    break;
                case 'dbname';
                    $this->dbName = $value;
                    break;
                case 'dbms';
                    $this->dbms = strtolower($value);
                    break;
                case 'user';
                    $this->user = $value;
                    break;
                case 'pass';
                    $this->pass = $value;
                    break;
            }
        }
    }
    /**
     * Determines the parent directory of the current location
     * @return the full path with termination /.
     */
    private function getParentLoc() {
        $curLoc = __FILE__;
        $parLoc = substr($curLoc, 0, strripos($curLoc, "/"));
        return($parLoc);
    }
    /**
     * This function should determine the available DBMSs and
     * intersect them with the supported DBMSs and then return the intersection.
     * Currently, only MySQL is supported so only mysql is returned.
     * @return <array> [mysql]
     */
    function determineAvailableDBMS() {
        $this->dbms = "mysql";
        $availDBMSs = array("mysql");
        return($availDBMSs);
    }
    /**
     * Getter functions follow
     */
    public function getDbms() {
        return($this->dbms);
    }
    public function getHost() {
        return($this->host);
    }
    public function getDbName() {
        return($this->dbName);
    }
    public function getUser() {
        return($this->user);
    }
    public function getPass() {
        return($this->pass);
    }
}
?>
